package pl.edu.mimuw.irs.core.model.analysis.resources;

import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import pl.edu.mimuw.irs.core.model.analysis.Time;
import pl.edu.mimuw.irs.core.model.analysis.dd.ActivityWrapper;
import pl.edu.mimuw.irs.core.model.design.net.IRSActivity;
import pl.edu.mimuw.irs.core.model.design.net.IRSWorkflow;
import pl.edu.mimuw.irs.core.model.design.resource.Requirement;
import pl.edu.mimuw.irs.core.model.design.resource.Resource;

public class ResourcesGraph implements Serializable {

	private static final long serialVersionUID = -1075365872877936481L;
	
	// *** Attributes

	private IRSWorkflow workflow;
	private Map<IRSActivity, ActivityWrapper> activities;
	private Map<Requirement, RequirementPlace> requirements;
	private Map<Resource, ResourcePlace> resources;
	private Time timestamp;
	// Getters and setters
	public IRSWorkflow getWorkflow() {
		return workflow;
	}
	public Map<IRSActivity, ActivityWrapper> getActivities() {
		if (activities == null) activities = new LinkedHashMap<IRSActivity, ActivityWrapper>();
		return activities;
	}
	public Map<Requirement, RequirementPlace> getRequirements() {
		if (requirements == null) requirements = new LinkedHashMap<Requirement, RequirementPlace>();
		return requirements;
	}
	public Map<Resource, ResourcePlace> getResources() {
		if (resources == null) resources = new LinkedHashMap<Resource, ResourcePlace>();
		return resources;
	}
	public Time getTimestamp() {
		if (timestamp == null) timestamp = new Time();
		return timestamp;
	}
	public void setTimestamp(Time timestamp) {
		this.timestamp = timestamp;
	}
	
	// *** Constructors
	
	public ResourcesGraph(IRSWorkflow irsWorkflow,
			Map<Requirement, RequirementPlace> requirements,
			Map<Resource, ResourcePlace> resources) {
		this.workflow = irsWorkflow;
		this.requirements = requirements;
		this.resources = resources;
		
		createWrappers(workflow.getActivities());
		
	}
	
	// *** Methods
	
//	public void start(ActivityWrapper activity, Set<RequirementPlace> set) {
//		/*
//		 * Here we have starting activity and set of requirements that will be made
//		 * busy by this start.
//		 */
//		for (RequirementPlace requirement : set) {
//			Set<ActivityWrapper> working = getNodes().get(requirement.getRequirement()).getWorkingActivities();
//			if (!working.contains(activity)) working.add(activity);
//		}
//		activity.setStarted(true);
//	}
//
//	public void end(ActivityWrapper activity) {
//		/*
//		 * Here we have ending activity and set of requirements that will be made
//		 * free by this end.
//		 */
//		for (RequirementPlace requirement : getBusyRequirements().get(activity.getActivity())) {
//			Set<ActivityWrapper> working = getNodes().get(requirement.getRequirement()).getWorkingActivities();
//			if (working.contains(activity)) working.remove(activity);
//		}
//		getBusyRequirements().remove(activity.getActivity());
//		activity.setStarted(false);
//	}
	
	private void createWrappers(Set<IRSActivity> activities) {
		Map<IRSActivity, ActivityWrapper> wrappers = getActivities();
		for (IRSActivity activity : activities) {
			wrappers.put(activity, new ActivityWrapper(activity));
		}
		
		/*
		 * Creating ancestry tree inside every wrapper.
		 */
		for (ActivityWrapper wrapper : wrappers.values()) {
			wrapper.setRootTimestamp(getTimestamp());
			wrapper.createDescendingPath(wrappers);
		}
	}
	
	public void reset() {
		setTimestamp(new Time());
		for (ActivityWrapper activity : activities.values()) {
			activity.reset();
			activity.setRootTimestamp(getTimestamp());
		}
	}
}
